#!/bin/bash
#!/usr/bin/expect

#==============[PART1] local var which need to be set in your system environment=============
AutoImportTools_path="/home/maminjie/tools/AutoImportTools"
check_script_path="$AutoImportTools_path/autoimport/checkspec/"
git_clone_path="/home/maminjie/work/checklicense/tmp"
editor_and_mail_info='maminjie <maminjie1@huawei.com>'
gitee_user_name='maminjie'
gitee_user_password=''

# set env path
export PYTHONPATH="$PYTHONPATH:$AutoImportTools_path"

#==============[PART1] local var which need to be set in your system environment,end=========

#==============[PART2] local var which need not be set in different environments=============
currpath=`pwd`
#function can only return int value,final result have to been defined here,
#and modified in function Generate_New_license_String(),though
result_string=""
#==============[PART2] local var which need not be set in different environments,end=========
##
## gitee
##
token_file=~/.gitee_token.json
if [ ! -f $token_file ]; then
    echo "Please see https://gitee.com/maminjie/fancytool/tree/master/python/sourcecounter to generate token!"; exit
fi
access_token=$(grep "access_token" $token_file | awk -F '[,:]' '{print $2}' | sed 's/"//g')
if [ -z $access_token ]; then
    echo "access_token is empty!"; exit
fi

__get_http_code() {
    local code=$(echo "$1" | awk -F 'ResponseCode:' '{print $2}')
    echo "$code"
}

# gitee_post(url, value)
gitee_post() {
    local result=$(curl -s -X POST -w ' ResponseCode:%{http_code}' --header "Content-Type: application/json;charset=UTF-8" "$1" -d "$2")
    echo "$result"
}

# fork_repo(repo)
fork_repo() {
    url="https://gitee.com/api/v5/repos/src-openeuler/$1/forks"
    value="{\"access_token\":\"$access_token\"}"
    result=$(gitee_post "$url" "$value")
    code=$(__get_http_code "$result")
    if [ "$code" != "201" ]; then
        return 1
    fi
    return 0
}

# check_personal_repo(repo)
check_personal_repo() {
    git_url="https://gitee.com/$gitee_user_name/$1"
    result=$(expect -c "
    spawn git ls-remote "$git_url"
    expect {
    \"*Username*\" {send "*"}
    \"*Password*\" {send "*"}
    }")
    result=$(echo "$result" | grep "Username")
    if [ -n "$result" ]; then
        return 1
    fi
    return 0
}

# clone_repo(repo)
clone_repo() {
    git_url="https://gitee.com/$gitee_user_name/$1.git"
    git clone "$git_url"
    if [ ! -d "$1" ]; then
        return 1
    fi
    return 0
}

##
## obs
##
changename() {
    service=_service

    if [ ! -f $service ]; then
        return;
    fi

    if [ $(ls $service* | wc -l) == 1 ]; then
        osc up -S 2> /dev/null
    fi

    rm -f $service

    for file in $(ls | grep -v .osc); do
        new_file=${file##*:}
        mv $file $new_file
    done
}

# checkout_package(pkg)
checkout_package() {
    # judge if current directory is a osc project
    ls -a .osc | grep _project > /dev/null 2>&1
    if [ $? != 0 ];then
        echo "This directory is not a osc project"
        return 1
    fi

    #download specified package
    osc co $1
    if [ ! -d "$1" ];then
        echo "$1 dose not exist in this osc project"
        return 1
    fi

    pushd $1
    changename
    popd

    return 0
}

gen_new_license() {
    add_license_string=""
    spec_license_changed_flag=0
    license_file="$check_script_path/LicenseList.txt"
    license_trans_file="$check_script_path/license_translations"
    #//parameter pre process, get src license array and its size,
    #//get spec license array and its size.
    src_trim_quot=${1//\'/}
    spec_trim_quot=${2//\'/}
    OLD_IFS="$IFS"; IFS=","
    src_licenses=($(echo "$src_trim_quot" | sed 's/,\s*/,/g'))
    spec_licenses=($(echo "$spec_trim_quot" | sed 's/,\s*/,/g'))
    IFS="$OLD_IFS"
    src_licenses_num=${#src_licenses[*]}
    spec_licenses_num=${#spec_licenses[*]}

    #//iteratly judge license in src array,wether it should be
    #//added into spec license cluster
    src_license_index=0
    while [ $src_license_index -le $((src_licenses_num-1)) ]; do
        pending_license=${src_licenses[$src_license_index]}
	    let src_license_index++

        #1.judge wether or not license in white_list
        license_type=$(grep -w "$pending_license," $license_file | awk -F ',' '{print $2}' | sed 's/^\s*//g')
        if [ "$license_type" = "black" ]; then
            echo "license $pending_license is not in white_list, can not add to spec file"
	        continue
        elif [ -z "$license_type" ]; then
            echo "license $pending_license is not in license list"
        fi

	    # judge wether or not license in spec license cluster
	    spec_license_index=0
	    while [ $spec_license_index -le $((spec_licenses_num-1)) ]; do
            spec_license=${spec_licenses[$spec_license_index]}
            current_index=$spec_license_index
            let spec_license_index++

            # pending_license == spec_license means pending_license has already exist in spec file
            if [ "$pending_license" == "$spec_license" ]; then
                echo "license $pending_license has already in spec file"
                continue 2
            fi

            # match license with license_translations file
            trans_license=$(grep -w "$spec_license," $license_trans_file | awk -F ',' '{print $2}' | sed 's/^\s*//g')
            if [ "$pending_license" = "$trans_license" ]; then
                echo "licenes $pending_license is equal to $spec_license"
                continue 2
            fi

            # pending_license == spec_license trim last char means pending_license was included in spec xxx+ license
            if [ "$pending_license+" == "${spec_license}" ]; then
                echo "license $pending_license was inincluded in $spec_license"
                continue 2
            fi

            # pending_license trim last char == spec_license means pending_license can replace spec license
            if [ "${pending_license}" == "$spec_license+" ]; then
                echo "license $pending_license contains spec license $spec_license, do replacement"
                spec_licenses[$current_index]="$pending_license"
                spec_license_changed_flag=1
                continue 2
            fi
        done

	    # execute to here means pending_license should be add to spec file
        add_license_string="$add_license_string and $pending_license"
    done

    #if new spec license list is not equla to old spec license list,
    #or add_license_string is not null, signify that license in spec file has been changed
    if [[ $spec_license_changed_flag -eq 1 ]] || [[ $add_license_string != "" ]];then
        #replace operation can make redundancy licenses,remove redundancy license here
        spec_licenses_remove_redundancy=($(echo ${spec_licenses[*]} | sed 's/ /\n/g' | sort | uniq))
        spec_string=''
        for item in ${spec_licenses_remove_redundancy[@]};do spec_string=$spec_string' and '$item;done
        spec_string=${spec_string#*' and '}
        new_spec_licenses_num=${#spec_licenses_remove_redundancy[*]}

        #generate final result license string
        result_string=$spec_string$add_license_string
        return 1 #return 1 means modifications exists in license info
    fi

    return 0 #return 0 means modifications dose not exists in license info
}

# update_spec(specfile)
update_spec() {
    spec_file="$1"
    # backup spec file
    cp $spec_file $spec_file~

    # get version string from spec file
    version_string=$(grep -w 'Version:' $spec_file)
    version_string=${version_string#*Version:}
    version_string=$(echo $version_string)

    # get old release unber form spec file
    old_release_line=$(grep -w 'Release:' $spec_file)
    old_release_string=${old_release_line#*Release:}
    old_release_string=$(echo $old_release_string)

    release_string=${old_release_string%%.*}  # in case 62.20200414 and 1.21.a2.2
    release_string=${release_string%\%*}      # in case %{?dist}
    release_num=$((10#${release_string}+1))
    release_string=$(echo $release_num)
    new_release_string=$release_string

    # generate version info and release id
    epoch_string=$(grep -w 'Epoch:' $spec_file)
    if [ -n "$epoch_string" ]; then
        epoch_string=${epoch_string#*Epoch:}
        epoch_string=$(echo $epoch_string)
        changelog_version_string="$epoch_string:$version_string-$new_release_string"
    else
        changelog_version_string="$version_string-$new_release_string"
    fi

    # replace release number in spec file
    sed -i "/Release:/{s/$old_release_string/$new_release_string/g}" $spec_file

    # get old license info
    old_license_line=$(grep -w 'License:' $spec_file)
    old_license_string=${old_license_line#*License:}
    old_license_string=$(echo $old_license_string)

    # replace license info in spec file
    sed -i "/License:/{s/$old_license_string/$result_string/g}" $spec_file

    # insert changelog info
    changelog_date_string=$(env LC_TIME=en_US.UTF-8 date +"%a %b %_d %Y")
    sed -i "/%changelog/a* $changelog_date_string $editor_and_mail_info - $changelog_version_string" $spec_file
    sed -i "/* $changelog_date_string/a- Modify license information." $spec_file
    sed -i "/- Modify license information./G" $spec_file
}

#===============[PART3] functions end=================================


#===============[PART4] main script===================================
#clear history mark
rm -rf $check_script_path/'license_review_pkgs/'$1

#check parameter
if [ $# -ne 1 ];then
    echo "Usage: licensediag packagename"
    exit 0
fi

checkout_package $1
if [ $? != 0 ]; then
    exit 0
fi

#check_script will be interrupted in these conditions:
#1.package contain jar ball
#2.package contain documents
#3.package contain .pom file   etc
#so ,we have to process package one by one.
#ensure that there is only one package in our project

packagenum=`ls | wc -l`
if [ $packagenum -ne 1 ];then
    echo "There must be only $1 packge in this project directory"
    exit 0
fi

#execute check script
pushd $check_script_path
python3 CheckSpec.py -p $currpath -d ~/PkgSource > $check_script_path/review_result.log 2>&1
popd

#sometime python check script move package directory to license_review_pkgs
#in this case,we should restore package to previous positon
if [ ! -d "$1" ];then
    if [ -d "$check_script_path/license_review_pkgs/$1" ]; then
        mv "$check_script_path/license_review_pkgs/$1" ./
    else
        checkout_package $1
    fi
fi

#do judgement whether or not the package need to add license to SPEC file
#cause sometime spec licenses are same as src licenses,in this case we do
#not need to do any work
pushd $check_script_path
license_diff=$(grep -rni 'licenses from source files are not same as form SPEC' review_result.log)
if [ -z "$license_diff" ]; then
    echo "licenses form source files are same as from SPEC"
    popd
    exit 0
fi
popd

#get license info from src files and SPEC file
pushd $check_script_path
src_license_info_line=`grep -rni 'all licenses from (' review_result.log`
spec_license_info_line=`grep -rni 'all licenses from SPEC' review_result.log`
popd
#src_license_info_line=${src_license_info_line// /}    #trim space charactors
#spec_license_info_line=${spec_license_info_line// /}

src_license_cluster=${src_license_info_line#*are:}    #extract license info which splited with ','
src_license_cluster=${src_license_cluster#*[}
src_license_cluster=${src_license_cluster%]*}
spec_license_cluster=${spec_license_info_line#*are:}
spec_license_cluster=${spec_license_cluster#*[}
spec_license_cluster=${spec_license_cluster%]*}
spec_license_cluster=${spec_license_cluster#*\{}
spec_license_cluster=${spec_license_cluster%\}*}

src_license_array=(${src_license_cluster//,/ })
echo "src  license cluster: [$src_license_cluster]"
echo "SPEC licesne cluster: [$spec_license_cluster]"
license_num=${#src_license_array[*]}

#if licenses form source files are [],we do not need to do any work
if [ $license_num -eq 0 ];then
    echo "no license extracted form source files"
    exit 0
fi

#invoke gen_new_license to get a new licenses info,if there
#is some changes in licenses info gen_new_license will return 1,
#otherwise return 0.new licenses info will be saved in result_string
gen_new_license "$src_license_cluster" "$spec_license_cluster" $1
change_or_not=$?
if [ $change_or_not -ne 1 ];then
    echo "No need to change license information"
    exit 0
else
    echo "License information changed to $result_string"
fi

#edit spec file
update_spec "$1/$1.spec"

#get remote git package

if [ ! -d "$git_clone_path" ]; then
    mkdir -p "$git_clone_path"
fi

if [ -d "$git_clone_path/$1" ]; then
    rm -rf "$git_clone_path/$1"
fi

pushd $git_clone_path

check_personal_repo $1
if [ $? != 0 ]; then
    fork_repo $1
    if [ $? != 0 ]; then
        echo "fork $1 failed"
        exit
    fi
    sleep 2
fi

clone_repo $1
if [ $? != 0 ];then
    echo "package $1 is not exist in personal remote repo"
    popd
    exit 0
fi
popd

#replace git project's spec file
cp -f $currpath/$1/$1.spec $git_clone_path/$1

#execute git push
pushd $git_clone_path/$1/
git add .
git commit -m "Modify license information"

#don't push now
if [ 0 == 1 ]; then
touch pushscript
chmod 744 pushscript
echo "#!/bin/expect -f
spawn git push
expect \"Username for 'https://gitee.com':\"
send \"$gitee_user_name\\r\"

expect \"Password for 'https://$gitee_user_name@gitee.com':\"
send \"$gitee_user_password\\r\"
interact" > pushscript
./pushscript
fi
popd

